package com.cskayan.javase.object._1getclass;

/**
 * Object类的getClass方法
 * 方法的声明:
 *      public final native Class<?> getClass();
 * 解释:
 *      1.访问权限不需要关注,因为它是public修饰的
 *      2.final修饰方法,表示不能被重写的方法
 *      3.native修饰方法,表示本地方法.本地方法不是java代码实现的方法,它不需要方法体
 *      4.Class<?> 处在返回值类型的位置
 *          Class是一个类名,是java.lang.Class类,表示返回它的对象
 *          <?>就是泛型,今天我们先不管泛型,因为Java的泛型对程序的运行没有影响,只影响编译.
 *      5.方法不需要参数.
 *
 * 这个方法返回一个Class对象,那么什么是Class对象,Class对象有什么用?
 * Class对象是JVM类加载某个类时,自动在堆上创建的一个封装了该类类型信息的对象
 *      程序运行期间,程序员可以通过获取这个对象,了解类型信息
 *      了解类型信息后,就可以对这个类进行一些操作,比如创建对象,赋值,调用方法等等
 *      这种利用Class对象来完成操作的技术,就是Java中的反射.
 *          所以反射并不高端,反射就是Class对象API的调用
 *          反射可以破解私有权限,反射基本是"为所欲为"
 *      Class类的对象是一个类或者接口的运行时类对象,封装了该类的类型信息.
 *
 * Class对象和getClass方法注意事项:
 *      1.某个类的Class对象不是程序员创建的,更不是getClass方法创建的,
 *          而是JVM在类加载某个类的同时在堆上创建的
 *
 *      2.某个类的类加载在程序的一次运行期间,最多只有一次
 *          那么某个类的Class对象(运行时类对象)也是唯一的
 *          而不同类型的Class对象必然不是同一个对象
 *      getClass在Java中最重要的用途就在这里
 *          是用来判断两个引用所指向的对象是否是同一个类型的对象
 *          比如:
 *              System.out.println(s.getClass() == s2.getClass());
 *              返回true就表示是同一个类型
 *              反之就不是同一个类型的对象
 *
 *  3.运行时类的Class对象只有一个，而类的对象可以有无数个。
 *  有时，我们也把类的运行时对象，Class对象称之为"类对象"。
 *  而具体的类的对象，称之为"类的对象"。当然我不建议，在学习中抠字眼，大家知道这个说法就行。
 *
 *  4.Class类对象是反射的基础，反射实际上就是Class类的API的调用。反射获取Class对象后，获取类型信息，还可以破解私有权限，反射在Java中可以称得上为所欲为。
 * 注：这里我们不讲反射，关于Class类的API使用，我们也不详细去讲。提供两个方法，大家可以简单使用一下：
 * // 获取类的全限定类名
 * getName()
 * // 获取类名
 * getSimpleName()
 * 通过getClass方法获取Class对象后，直接调用方法即可。
 *
 *
 * @since 14:53
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Student s = new Student();
        Class stuClazz = s.getClass();

        Student s2 = new Student();
        Class stuClazz2 = s2.getClass();
        // ==比较地址,只有当两个引用指向同一个对象时,才返回true
        System.out.println(stuClazz == stuClazz2);

        Teacher t = new Teacher();
        Class teacherClazz = t.getClass();
        System.out.println(teacherClazz == stuClazz);

        System.out.println(s.getClass() == s2.getClass());
        /*
            ==连接引用数据类型
            必须左右两边是同种数据类型
            而泛型会影响编译
            Class<? extends Teacher>
            和
            Class<? extends Student>
            这两个泛型不同的Class类型
            在编译器看来就不是同种数据类型
         */
        // Operator '==' cannot be applied to 'java.lang.Class<capture<? extends com.cskayan.javase.object._1getclass.Teacher>>', 'java.lang.Class<capture<? extends com.cskayan.javase.object._1getclass.Student>>'
        Class<? extends Teacher> clazz1 = t.getClass();
        Class<? extends Student> clazz2 = s.getClass();
        // System.out.println(t.getClass() == s.getClass());

        Object o1 = t;
        Object o2 = s;
        // 下列语句返回false,说明o1和o2不是同种类型的对象
        System.out.println(o1.getClass() == o2.getClass());


        System.out.println("-------------");
        System.out.println(stuClazz.getName());
        System.out.println(stuClazz.getSimpleName());
    }
}

class Student {
}

class Teacher {

}